home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Trading on the Edge
/
Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin
/
pc
/
mac_file
/
vendor_d
/
ga_softw
/
ooga
/
rep-meth.lis
< prev
next >
Wrap
File List
|
1991-02-03
|
15KB
|
461 lines
;;; -*- Mode:Lisp; Package:OOGA; Base:10; Syntax:COMMON-LISP -*-
#||
RESTRICTED RIGHTS LEGEND
Use, duplication, or disclosure by the Government is subject to
restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
Technical Data and Computer Software Clause at 52.227-7013 of the DOD
FAR Supplement.
TSP (The Software Partnership)
P.O. Box 991
Melrose, MA 02176
Copyright 1990 by Lawrence Davis and Daniel Cerys, all rights reserved.
||#
(in-package :ooga)
;;; This file contains methods contained in the reproduction
;;; module
;************************************************************
; OPERATOR SELECTION TECHNIQUE
(defmethod INITIALIZE-FOR-RUN ((technique operator-selection-technique))
t)
;;; Operator selection techniques select operators for
;;; reproduction events.
;;; Use first operator uses the first operator on the list. It
;;; shouldn't be used when there is more than one operator.
(defmethod GET-OPERATOR ((use-first-operator use-first-operator))
(first (operator-list (reproduction-module use-first-operator))))
;;; Roulette wheel operator selection chooses operators with
;;; probabilities biased by operator weights.
(defmethod GET-OPERATOR ((technique roulette-wheel-operator-selection))
(let ((reproduction-module (reproduction-module technique)))
(get-associated-total-list-element
(operator-list reproduction-module)
(operator-weights reproduction-module)
(random (apply '+ (operator-weights reproduction-module))))))
;************************************************************
; REPRODUCTION PARAMETERIZATION TECHNIQUES
;;; Set the operator weights to their initial value.
(defmethod INITIALIZE-FOR-RUN ((technique interpolate-operator-weights))
(setf (operator-weights (reproduction-module technique))
(car (interpolation-specs technique))))
;;; Interpolate operator weights at given increments.
(defmethod MODIFY-PARAMETERS
((technique interpolate-operator-weights)
portion-completed size-of-interval)
(if (even-multiple portion-completed (interpolation-interval technique))
(setf (operator-weights (reproduction-module technique))
(interpolate-from-spec (car (interpolation-specs technique))
(cadr (interpolation-specs technique))
size-of-interval
portion-completed))))
;************************************************************
; REPRODUCTION MODULE
;;; Drive the initialization of the module and its techniques.
(defmethod INITIALIZE-FOR-RUN
((reproduction-module basic-reproduction-module))
(setf (reproduction-module (operator-selection-technique reproduction-module))
reproduction-module)
(loop for technique in (parameterization-techniques reproduction-module)
do (setf (reproduction-module technique) reproduction-module))
(loop for operator in (operator-list reproduction-module)
do (setf (reproduction-module operator) reproduction-module))
(initialize-for-run (operator-selection-technique reproduction-module))
(loop for technique in (parameterization-techniques reproduction-module)
do (initialize-for-run technique)))
;;; Create a new generation of population members.
(defmethod REPRODUCE ((reproduction-technique generational-replacement)
(reproduction-module basic-reproduction-module))
(loop with new-members = nil
with number-to-create = (population-size
(population-module reproduction-technique))
until (>= (length new-members) number-to-create)
do (setf new-members
(append new-members
(create-new-members reproduction-module)))
finally (return (firstn number-to-create new-members))))
;;; As above, with elitism
(defmethod REPRODUCE ((reproduction-technique generational-replacement-with-elitism)
(reproduction-module basic-reproduction-module))
(loop with new-members = (list (first-member (population-module (ga reproduction-module))))
with number-to-create = (population-size
(population-module reproduction-technique))
until (>= (length new-members) number-to-create)
do (setf new-members
(append new-members
(create-new-members reproduction-module)))
finally (return (firstn number-to-create new-members))))
;;; Run one operator and return the children
(defmethod REPRODUCE ((reproduction-technique steady-state)
(reproduction-module basic-reproduction-module))
(create-new-members reproduction-module))
;;; Create new members. Only pass those back that are not
;;; duplicates of existing members. Halt the run if too many
;;; duplicates have been produced.
(defmethod REPRODUCE ((reproduction-technique steady-state-without-duplicates)
(reproduction-module basic-reproduction-module))
(let* ((new-members (create-new-members reproduction-module))
(unduplicated-members
(loop for new-member-list on new-members
with population-module = (population-module
(ga reproduction-module))
unless (or (loop for other-member in (cdr new-member-list)
thereis (chromosome-equal
(chromosome other-member)
(chromosome (car new-member-list))))
(chromosome-exists
(car new-member-list) population-module))
collect (car new-member-list))))
(setf (duplicate-tally reproduction-technique)
(+ (duplicate-tally reproduction-technique)
(- (length new-members)
(length unduplicated-members))))
(if (< (duplicate-tally reproduction-technique)
(maximum-duplicates reproduction-technique))
unduplicated-members
(progn (setf (stop-run? (population-module (ga reproduction-module)))
(append (stop-run? (population-module
(ga reproduction-module)))
(list (format
nil
"MAXIMUM DUPLICATE NUMBER ~a EXCEEDED"
(maximum-duplicates
reproduction-technique)))))
nil)
)))
;;; Apply an operator and return population members containing the
;;; resulting chromosomes.
(defmethod CREATE-NEW-MEMBERS
((reproduction-module basic-reproduction-module))
(loop with population-module = (population-module
(ga reproduction-module))
for chromosome in (apply-operator
(get-operator
(operator-selection-technique
reproduction-module))
population-module)
for new-member = (create-population-member
(initialization-technique population-module)
(representation-technique population-module))
collect (progn (setf (chromosome new-member) chromosome)
new-member)))
;;; Does the chromosome already exist in the population?
(defmethod CHROMOSOME-EXISTS
((member population-member)
(population-module basic-population-module))
(loop for existing-member = (first-member population-module)
then (successor existing-member)
until (null existing-member)
do (if (chromosome-equal
(chromosome member)
(chromosome existing-member))
(return t))
finally (return nil)))
;;; REDEFINE THIS METHOD WHENEVER USING CHROMOSOMES
;;; THAT AREN'T LISTS
(defmethod CHROMOSOME-EQUAL ((chromosome1 t) (chromosome2 t))
(equal chromosome1 chromosome2))
;;;************************************************************
;;;************************************************************
;;; OPERATOR METHODS
;;;************************************************************
;;;************************************************************
;NOTE THAT ALL OPERATORS SHOULD RETURN A LIST OF CHILDREN.
;The message interface to operators is: operators can call (get-parent optimizer)
;multiple times if needed.
;Operators should return a list of children. This list can be null.
(defgeneric APPLY-OPERATOR (operator basic-population-module)
#-:pcl
(:documentation "Apply OPERATOR to some apropriate portion of the population.
This returns a list of new population members."))
;************************************************************
; ONE POINT CROSSOVER AND MUTATE
(defmethod APPLY-OPERATOR ((operator one-point-crossover-and-mutate)
(population-module basic-population-module))
"Cross two parents over at a single point to make two children"
(let* ((list1 (chromosome (get-parent population-module)))
(list2 (chromosome (get-parent population-module)))
(bit-mutation-rate (bit-mutation-rate operator)))
(if (probability-test (crossover-rate operator))
(loop for list in (one-point-crossover list1 list2)
collect (mutate-bits bit-mutation-rate list))
(list (mutate-bits bit-mutation-rate list1)
(mutate-bits bit-mutation-rate list2)))))
;************************************************************
; ONE POINT CROSSOVER
(defmethod APPLY-OPERATOR ((operator one-point-crossover)
(population-module basic-population-module))
"Cross two parents over at a single point to make two children"
(one-point-crossover (chromosome (get-parent population-module))
(chromosome (get-parent population-module))))
;************************************************************
; TWO-POINT CROSSOVER
(defmethod APPLY-OPERATOR ((operator two-point-crossover)
(population-module basic-population-module))
"Cross two parents over at two points to make two children"
(two-point-crossover (chromosome (get-parent population-module))
(chromosome (get-parent population-module))))
;************************************************************
; BINARY MUTATION
(defmethod APPLY-OPERATOR ((operator binary-mutation)
(population-module basic-population-module))
"Mutate bits on a parent to make a child"
(list (mutate-bits (bit-mutation-rate operator)
(chromosome (get-parent population-module)))))
;************************************************************
; UNIFORM LIST CROSSOVER
(defmethod APPLY-OPERATOR ((operator uniform-list-crossover)
(population-module basic-population-module))
"Do uniform crossover of elements in two lists of equal length"
(loop with parent1 = (nreverse (copy-list
(chromosome (get-parent population-module))))
with parent2 = (nreverse (copy-list
(chromosome (get-parent population-module))))
with child1
with child2
for element1 in parent1
for element2 in parent2
do (if (= 0 (random 2))
(setf child1 (cons element1 child1)
child2 (cons element2 child2))
(setf child1 (cons element2 child1)
child2 (cons element1 child2)))
finally (return (list child1 child2))))
;************************************************************
; RANDOM BIT STRING GENERATION
(defmethod APPLY-OPERATOR ((operator random-bit-string-generation)
(population-module
basic-population-module))
"Generate a list of random bits"
(list (create-random-bit-string
(bit-string-length (representation-technique population-module)))))
;************************************************************
; REAL NUMBER MUTATION
(defmethod APPLY-OPERATOR ((operator real-number-mutation)
(population-module basic-population-module))
"Replace values of a real-valued chromosome with randomly-chosen
values according to the spec and the probability"
(list
(loop with probability = (mutation-rate operator)
for field in (copy-list (chromosome (get-parent population-module)))
for specs = (mutation-specs operator)
then (if (cdr specs) (cdr specs) specs)
collect (if (probability-test probability)
(make-random-value (caar specs) (cadar specs) (caddar specs))
field))))
;************************************************************
; REAL NUMBER CREEP
(defmethod APPLY-OPERATOR ((operator real-number-creep)
(population-module basic-population-module))
"Creep elements in a lists of real numbers according to the creep spec"
(list
(loop with probability = (creep-rate operator)
with chromosome = (chromosome (get-parent population-module))
for field in chromosome
for specs = (creep-specs operator)
then (if (cdr specs) (cdr specs) specs)
collect (if (probability-test probability)
(creep-value specs field) field))))
;************************************************************
; AVERAGE CROSSOVER
(defmethod APPLY-OPERATOR ((operator average-crossover)
(population-module basic-population-module))
"Average fields in two real-valued parents to make one child"
(list (let ((chromosome1 (chromosome (get-parent population-module)))
(chromosome2 (chromosome (get-parent population-module))))
(loop for field1 in chromosome1 for field2 in chromosome2
collect (integer-average field1 field2)))))
;************************************************************
; AVERAGE REAL CROSSOVER
(defmethod APPLY-OPERATOR ((operator average-real-crossover)
(population-module basic-population-module))
"Average fields in two real-valued parents to make one child"
(list (let ((chromosome1 (chromosome (get-parent population-module)))
(chromosome2 (chromosome (get-parent population-module))))
(loop for field1 in chromosome1 for field2 in chromosome2
collect (/ (+ field1 field2) 2.0)))))
;************************************************************
; UNIFORM ORDER-BASED CROSSOVER
(defmethod APPLY-OPERATOR ((operator uniform-order-based-crossover)
(population-module basic-population-module))
"Cross two parents over using a binary template and re-ordering of some components"
(let* ((parent1 (chromosome (get-parent population-module)))
(parent2 (chromosome (get-parent population-module)))
(template (create-random-bit-string (length parent1)))
(parent1-scramble-set (get-scramble-set parent1 parent2 template))
(parent2-scramble-set (get-scramble-set parent2 parent1 template))
(child1 (template-assemble template parent1 parent1-scramble-set))
(child2 (template-assemble template parent2 parent2-scramble-set)))
(list child1 child2)))
;************************************************************
; SCRAMBLE SUBLIST MUTATION
(defmethod APPLY-OPERATOR ((operator SCRAMBLE-SUBLIST-MUTATION)
(population-module basic-population-module))
"Return the result of scrambling a sublist of the parent."
(let ((parent (chromosome (get-parent population-module))))
(multiple-value-bind (cut-point1 cut-point2)
(get-two-cut-points (length parent))
(list (scramble-sublist parent cut-point1 cut-point2)))))
;************************************************************
; RANDOM ORDER GENERATION
(defmethod APPLY-OPERATOR ((operator RANDOM-ORDER-GENERATION)
(population-module
basic-population-module))
"Return a random permutation of the master list"
(list (nscramble (copy-list (list-to-permute
(initialization-technique population-module))))))